package com.shujia.data_safe;


import com.shujia.share.NumberCount;
import com.shujia.share.ShareDemo2;

public class ShareDemo4 extends Thread {

    private NumberCount numberCount;
    private Object lock;
    // 单例, 在一个系统里面对象只有一个
    private final static Object lock2 = new Object();


    public ShareDemo4(String name, NumberCount numberCount, Object lock) {
        super(name);// 设置线程名称
        this.numberCount = numberCount;
        this.lock = lock;
    }

    public static void main(String[] args) {

//        // 创建共享资源
        NumberCount count = new NumberCount();
        Object lock = new Object();

        Thread t1 = new ShareDemo4("线程1", count, lock);
        Thread t2 = new ShareDemo4("线程2", count, lock);

        NumberCount count1 = new NumberCount();
        Thread t3 = new ShareDemo4("线程3", count1, lock);


        // 在一个JVM里面一个类的对象只有一个
//        Class<? extends Thread> aClass = t1.getClass();
//        Class<? extends Thread> aClass1 = t2.getClass();
//        System.out.println(aClass == aClass1);
//        System.out.println(aClass == ShareDemo2.class);
//        System.out.println(aClass1 == ShareDemo2.class);


        t1.start();
        t2.start();

        // join 让主线程等待子线程执行完毕再继续执行
        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(count.count);

    }

    /*
    synchronized 同步代码块, 很影响性能, 尽量只包围共享资源的代码
     */
    @Override
    public void run() {
        for (int i = 0; i < 50000; i++) {
            /*
            this就是一个监视器, 不同的线程代表了不同的对象
            synchronized (this) 锁的是不同的线程
            在加锁的时候, 一定要注意使用的是同一把锁才能保证原子性
             */
            // 共享资源
            synchronized (numberCount) {// 推荐
//            synchronized (lock) {
//            synchronized (lock2) {
//            synchronized (ShareDemo.class) { // 当前与用 synchronized 修饰了静态方法效果一致
            /*
             ShareDemo.class 返回时class对象, 一个类对应的class对象在当前的JVM里面只会存在一个
             锁的面就太广了, 如果有2个线程, 资源没有共享, 这2个线程也会互斥
             */
                numberCount.count++;
            }

            // 非共享资源, 本来就没有数据安全问题, 不需要加锁
            // ...

        }
    }


//    @Override
//    public void run() {
//        for (int i = 0; i < 50000; i++) {
////            try {
////                Thread.sleep(1);
////            } catch (InterruptedException e) {
////                e.printStackTrace();
////            }
//
////            System.out.println(getName() + ":" + numberCount.getCount());
//            numberCount.incr();
//        }
//    }
}
